//   Copyright 2010 Shantanu Shah<shantanus@gmail.com>
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

package com.shansense.coretimer;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Parcelable;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TimePicker;
import android.widget.Toast;
import android.widget.TimePicker.OnTimeChangedListener;

/**
 * The Activity for timers. Displays dialog box to set time, calls the service
 * by setting alarm.
 * 
 * @author Shantanu Shah <shantanus@gmail.com>
 */
public abstract class AbsChangeModeTimer {

  /**
   * Value to increment/decrement when you hit + on the minutes.
   */
  private static final int CHANGE_INTERVAL = 15;

  /**
   * Saved value identifiers in Preferences. Note that the actual string is irrelevant, it only
   * needs to be unique.
   * 0 = last saved value. Seekbar set to this value.
   * 1-3 = previous saved values. Buttons are created for these values. If 0, no button is created.
   */
  public static final String[] PREF_SAVED_TIME = { "prefs_saved_0", "prefs_saved_1",
      "prefs_saved_2", "prefs_saved_3" };

  /**
   * Values corresponding to PREF_SAVED_TIME ids.
   */
  private static long[] savedMillis = new long[PREF_SAVED_TIME.length];
  
  /**
   * Extra set in shortcut intent. This identifies a shortcut.
   */
  public static final String EXTRA_TIME_MILLIS = "com.shansense.coretimer.EXTRA_TIME_MILLIS";

  /**
   * Extra set in shortcut intent. This identifies the tab.
   */
  public static final String EXTRA_TAB_INDEX = "com.shansense.coretimer.EXTRA_TAB_INDEX";

  /**
   * Which tab was active when the app was used last time.
   */
	public static final String PREF_TAB_INDEX = "com.shansense.coretimer.PREF_TAB_INDEX";
  
  private static String appName;
  private TimePicker timePicker;
  private ChangeModePlugin plugin;
  private Activity parentActivity;
  
  public abstract ChangeModePlugin getPlugin();

	private static final OnTimeChangedListener nullOnTimeChangedListener =
		new OnTimeChangedListener() {
		@Override
		public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
			// Do nothing
		}
	};
  
  /**
   * Init the timer, does UI init.
   * @param defaultTime - if non-zero, will init timer to this value in ms.
   */
  public void init(long defaultTimeMilis) {
    plugin = getPlugin();
    appName = plugin.getAppName();
    parentActivity = plugin.getActivity(); 
    
    initSavedButtons();
    initButtonOK();
    initButtonCancel();
    initButtonUnsetMode();
    initTimePicker(defaultTimeMilis);
    initButtonShare();
    initButtonShortcut();
    initButtonMarket();
    initButtonHelp();
  }

  public int getSavedTabOrZero() {
  	SharedPreferences settings = parentActivity.getSharedPreferences(appName, 0);
  	return settings.getInt(PREF_TAB_INDEX, 0);
  }
  
  private void initSavedButtons() {
    // TODO- will need to segregate prefs
    SharedPreferences settings = parentActivity.getSharedPreferences(appName, 0);
    int totalButtons = 0;
    final OnClickListener savedButtonOnClickListener = new OnClickListener() {
      
      @Override
      public void onClick(View button) {
        final Long millis = (Long)button.getTag();
        ChangeModeUtil.setTimer(plugin, millis);
        parentActivity.finish();
      }
    };
    
    // Start from 1, since 0 is last value, filled in.
    for (int i=1; i<PREF_SAVED_TIME.length; i++) {
      savedMillis[i] = settings.getLong(PREF_SAVED_TIME[i], 0);
      final Button buttonSaved = plugin.getSavedButton(PREF_SAVED_TIME[i]);
      if (savedMillis[i] == 0) {
        buttonSaved.setVisibility(View.GONE);
      } else {
        totalButtons++;
        buttonSaved.setText(millisToDisplayableString(savedMillis[i]));
        buttonSaved.setTag(savedMillis[i]);
        buttonSaved.setOnClickListener(savedButtonOnClickListener);
      }
    }
    if (totalButtons == 0) {
      plugin.hideQuickSelect();
    }
  }

  private void initButtonOK() {
    Button buttonOK = plugin.getButtonOK();
    buttonOK.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View button) {
        final long millis = getTimeShownInMillis();
        ChangeModeUtil.setTimer(plugin, millis);
        ChangeModeUtil.savePreferences(plugin, savedMillis, millis);
        parentActivity.finish();
      }
    });
  }

  private void initButtonCancel() {
    final Button buttonCancel = plugin.getButtonCancel();
    buttonCancel.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View button) {
        parentActivity.finish();
      }
    });
  }

  private void initButtonUnsetMode() {
    Button buttonUnset = plugin.getButtonUnset();
    if (!plugin.isModeSet()) { //change. show only when notif visible? TODO
      buttonUnset.setVisibility(View.GONE);
      return;
    }
    buttonUnset.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick(View button) {
        ChangeModeUtil.setTimer(plugin, 0);
        parentActivity.finish();
      }
    });
  }
  
  private void initTimePicker(long defaultTimeMilis) {
    timePicker = plugin.getTimePicker();
    
    final OnTimeChangedListener onTimeChangedListener = new OnTimeChangedListener() {
      
      @Override
      public void onTimeChanged(TimePicker timePicker, int hours, int minutes) {
        
        if (minutes % CHANGE_INTERVAL != 0) {  // else we already have the right value.
          int timeInMinutes = hours * 60 + minutes;
          boolean wasOneMinuteChange = false;
          Integer oldMinutes = (Integer) timePicker.getTag();  // tag should never be null.
          if (oldMinutes == (minutes + 1) % 60) { // %60 to catch 0 -> 59
            wasOneMinuteChange = true;
            if (oldMinutes == 0 && timeInMinutes > 60) {
              // for transition 0 -> 45, decrement hour.
              timeInMinutes -= 60;
            }
          } else if (oldMinutes == (minutes - 1) % 60) { // %60 to catch 59 -> 0
            wasOneMinuteChange = true;
            // since we floor timeInMinutes, add CHANGE_INTERVAL now.
            timeInMinutes += CHANGE_INTERVAL;
          }
          // will remain false if was modified by more than 1, maybe using a keyboard
          if (wasOneMinuteChange) {
            timeInMinutes -= ((timeInMinutes % CHANGE_INTERVAL)); // floor
            timePicker.setOnTimeChangedListener(nullOnTimeChangedListener); // detach
            timePicker.setCurrentHour(timeInMinutes / 60);
            timePicker.setCurrentMinute(timeInMinutes % 60);
            timePicker.setOnTimeChangedListener(this); // re-attach
          }
        }  // min % CHANGE_INTERVAL
        timePicker.setTag(timePicker.getCurrentMinute());  // always set tag
      }
    };
    
    timePicker.setIs24HourView(true);
    SharedPreferences settings = parentActivity.getSharedPreferences(appName, 0);
    savedMillis[0] = settings.getLong(PREF_SAVED_TIME[0], 0);
    long initMilis = (defaultTimeMilis > 0) ? defaultTimeMilis : savedMillis[0];
    int newMinutes = 0;
    if (initMilis != 0) {
      int savedMin = (int) (initMilis / (60 * 1000));
      newMinutes = savedMin % 60;
      timePicker.setCurrentMinute(newMinutes);
      timePicker.setCurrentHour(savedMin / 60);
    } else {
      timePicker.setCurrentMinute(0);
      timePicker.setCurrentHour(0);
    }
    timePicker.setTag(newMinutes);
    timePicker.setOnTimeChangedListener(onTimeChangedListener);
  }

  
  private void initButtonShare() {
    Button buttonShare = plugin.getButtonShare();

    buttonShare.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick(View button) {
        Intent sendIntent = new Intent(Intent.ACTION_SEND);
        sendIntent.putExtra(Intent.EXTRA_TEXT, plugin.getShareText());
        sendIntent.setType("text/plain");
        parentActivity.startActivity(Intent.createChooser(sendIntent, "Share " + appName));
      }
    });
  }

  private void initButtonShortcut() {
    final Context context = parentActivity;
    final Button buttonShortcut = plugin.getButtonShortcut();

    buttonShortcut.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick(View view) {
        long timeShownInMillis = getTimeShownInMillis();
        Intent shortcutIntent = new Intent();
        shortcutIntent.setClassName(context,
        		parentActivity.getPackageName() + "." + appName + "Shortcut");
        if (timeShownInMillis == 0) {
          buttonShortcut.post(new Runnable() {
            @Override
            public void run() {
              Toast.makeText(context, "Set time first", Toast.LENGTH_SHORT).show();
            }
          });
          return;
        }
        shortcutIntent.putExtra(EXTRA_TIME_MILLIS, timeShownInMillis);
        int tabIndex;
        if ((tabIndex = plugin.getTabIndexIfPresent()) >= 0) {
        	shortcutIntent.putExtra(EXTRA_TAB_INDEX, tabIndex);	
        }
        Intent intent = new Intent();
        intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
        final String shortcutTime = millisToDisplayableString(timeShownInMillis);
        intent.putExtra(Intent.EXTRA_SHORTCUT_NAME,
            shortcutTime + " " + plugin.getShortcutName());
        Parcelable iconResource = Intent.ShortcutIconResource.fromContext(context, plugin
            .getApplicationIcon());
        intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);

        intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
        parentActivity.getApplicationContext().sendBroadcast(intent);
        
        buttonShortcut.post(new Runnable() {
          @Override
          public void run() {
            Toast.makeText(context,
                shortcutTime + " shortcut created on home screen",
                Toast.LENGTH_SHORT).show();
          }
        });
      }

    });
  }

  private void initButtonMarket() {
    Button buttonMarket = plugin.getButtonMarket();

    buttonMarket.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick(View arg0) {
        Intent sendIntent = new Intent(Intent.ACTION_VIEW);
        sendIntent.setData(Uri.parse("market://search?q=pub:\"Shantanu Shah\""));
        parentActivity.startActivity(sendIntent);
      }
    });
  }

  private void initButtonHelp() {
    final Context context = parentActivity;
    Button buttonHelp = plugin.getButtonHelp();
    buttonHelp.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View button) {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setCancelable(true)
        .setMessage("1. Set custom duration using keyboard. You can set any duration you want," +
        		" like 10 minutes.\n\n" +
        		"2. The shortcut button creates a 1-click shortcut on home screen." +
        		" You can create and delete as many shortcuts as you want.")
        .setNeutralButton("OK", new DialogInterface.OnClickListener() {
  
          @Override
          public void onClick(DialogInterface dialog, int unused) {
            dialog.dismiss();
          }
        })
        .show();
      }
    });
  }

  private String millisToDisplayableString(long timeShownInMillis) {
    StringBuilder shortcutPrefix = new StringBuilder();

    long totalMinutes = (timeShownInMillis / 1000) / 60;
    int minute = (int) (totalMinutes % 60);
    int hour = (int) (totalMinutes / 60);
    if (hour != 0) {
      shortcutPrefix.append(hour);
      shortcutPrefix.append("h");
    }
    if (minute != 0) {
      shortcutPrefix.append(minute);
      shortcutPrefix.append("m");
    }
    return shortcutPrefix.toString();
  }

  public long getTimeShownInMillis() {
    timePicker.clearFocus();
    int hours = timePicker.getCurrentHour();
    int min = timePicker.getCurrentMinute();
    
    return (hours * 60 + min) * 60 * 1000;
  }

}
